package com.framework.modules.base.controller;

import java.util.Date;
import java.util.Map;

import com.framework.common.config.SystemConfigName;
import com.framework.common.exception.RRException;
import com.framework.common.sms.SmsResponse;
import com.framework.common.utils.DateUtils;
import com.framework.common.utils.HttpContextUtils;
import com.framework.common.utils.QuickHelper;
import com.framework.form.RegisterForm;
import com.framework.modules.base.entity.TokenEntity;
import com.framework.modules.base.entity.UserEntity;
import com.framework.modules.base.entity.UserInfoEntity;
import com.framework.modules.base.entity.ValidateCodeEntity;
import com.framework.modules.base.service.UserInfoService;
import com.framework.modules.base.service.ValidateCodeService;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.hibernate.validator.internal.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.DependsOn;
import org.springframework.web.bind.annotation.*;

import com.framework.common.annotation.Login;
import com.framework.common.utils.R;
import com.framework.common.validator.ValidatorUtils;
import com.framework.form.LoginForm;
import com.framework.modules.base.service.TokenService;
import com.framework.modules.base.service.UserService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 登录接口
 */
@RestController
@RequestMapping("/auth")
@Api(tags = "登录注册")
public class ApiLoginController {

	protected Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private UserService userService;

	@Autowired
	private UserInfoService userInfoService;

	@Autowired
	private ValidateCodeService validateCodeService;

	@Autowired
	private TokenService tokenService;

	/**
	 * 获取验证码，当 mode=virtual 时，发送虚拟验证码
	 * @param mobile 手机号码
	 * @param mode virtual = 虚拟验证码
	 * @return
	 */
	@CrossOrigin
	@PostMapping("get_mobile_code")
	@ApiOperation("获取验证码")
	public R get_mobile_code(String mobile, String mode) {

		if(StringHelper.isNullOrEmptyString(mobile)){
			return R.error("请输入您的手机号码 !");
		}
		/*mode = QuickHelper.checkStringOrDefaultValue(mode,"");*/

		boolean debug=QuickHelper.getConfigValue(SystemConfigName.DEBUG,Boolean.class);
		//发送虚拟验证码 调试模式发虚拟验证码
		if(debug){
			ValidateCodeEntity entity = new ValidateCodeEntity();
			Integer rnd = QuickHelper.get_random_code(6000,9999);
			entity.setMob(mobile);
			entity.setState(0);
			entity.setCode(rnd.toString());
			entity.setAdddate(DateUtils.getSecondTimestamp(new Date()));
			entity.setAddlog("虚拟验证码");
			entity.setType("virtual");
			entity.setUid(0);
			validateCodeService.insert(entity);
			return R.ok("虚拟验证码发送成功").put("ext",rnd);
		}


		//检查今日验证码获取次数 调试模式不进行条数验证
		if(!debug) {
			//判断是否已经发送了验证码，防止多次发送 60s只能发一次
			Integer smsConfigCInterval=QuickHelper.getConfigIntegerValue(SystemConfigName.SMS_CONFIG_INTERVAL);
			ValidateCodeEntity codeEntity = validateCodeService.getLastValidCodeEntry(mobile, smsConfigCInterval);
			if(codeEntity!=null){
				return R.ok("验证码已发送成功");
			}

			Integer count = validateCodeService.checkDailyCodeCount(mobile);
			Integer maxSmsSendCount=QuickHelper.getConfigIntegerValue(SystemConfigName.SMS_CONFIG_MAX_DAILY_COUNT);
			if (count >= maxSmsSendCount && !debug) {
				return R.error("您短时间内获取验证码次数过多，请稍后重试");
			}
		}

		//return R.ok("成功").put("times",count);
		//校验短信验证码，防止重复发送

		Integer rnd = QuickHelper.get_random_code(6000,9999);
		SmsResponse res = validateCodeService.sendValidateCode(mobile,rnd.toString());
		if(res.getState() == SmsResponse.State.Success){
			return R.ok("验证码发送成功");
		}
		return R.ok(String.format("验证码发送失败,失败原因：%s", res.getRaw()));
	}


	/**
	 * 注册/登录
	 * 当系统为调试模式时，将不会再判断验证码是否正确
	 * 如果响应体中包含 isNewUser = true ,则继续补全信息，否则进入主界面code=-101为token失效
	 * @param form
	 * @return 返回token 登录之后所有接口访问token加入到header中
	 */
	@CrossOrigin
	@PostMapping("register")
	@ApiOperation("登陆(自动注册)")
	public R register(RegisterForm form) {

		//1.表单校验
		ValidatorUtils.validateEntity(form);

		String code = form.getValidateCode();
		String mobile = form.getMobile();


		//2.查询是否有获取过的短信
		boolean debug = QuickHelper.getConfigValue(SystemConfigName.DEBUG, Boolean.class);
		if (!debug) {
			Integer smsValidSeconds = QuickHelper.getConfigIntegerValue(SystemConfigName.SMS_CONFIG_VALIDSECONDS);
			ValidateCodeEntity codeEntity = validateCodeService.getLastValidCodeEntry(mobile, smsValidSeconds);
			//检查验证码是否获取 ?
			if (codeEntity == null) {
				return R.error("您还没有获取过验证码或者您的验证已过期，请重新再试 !");
			}

			if (!codeEntity.getCode().equals(code)) {
				return R.error( "手机验证码填写错误，请重新获取! ");
			}
		}

		Long uid = 0l;
		UserEntity entity = userService.queryByMobile(mobile);

		//3.如果用户不存在，则创建用户
		if (entity == null) {
			uid = userService.register(form);
			logger.info(String.format("新用户注册成功,用户编号：%s", uid));
			logger.trace("用户信息", entity);
		} else {
			uid = entity.getUserId();
		}
		//检查是否完善用户信息
		UserInfoEntity userInfoEntity = userInfoService.selectById(uid);

		//4.登录
		LoginForm loginForm = new LoginForm();
		loginForm.setUsername(form.getMobile());
		loginForm.setValidateCode(code);
		loginForm.setPassword("not_need_password");
		loginForm.setMode("mobile");
		loginForm.setPlatform(form.getPlatform());
		loginForm.setIsInternalLogin(1);
		//5.内部登录
		R res = this.login(loginForm);

		if ((int) res.get("code") > 0) {
			//res.put("token",res)
			return R.ok("登录成功")
					.put("uid", uid)
					.put("isNewUser", userInfoEntity == null)
					.put("ref", res);
		}
		return R.error("登录失败，请检查您的手机验证码是否输入正确");
	}


	/**
	 * 用户登陆(预留不用)
	 * @param form 登陆表单
	 * @return
	 */
	@PostMapping("login")
	@ApiOperation("登录(预留不用)")
	public R login(LoginForm form) {
		// 表单校验
		ValidatorUtils.validateEntity(form);
		String mobile = form.getUsername();

		//2.查询是否有获取过的短信
		boolean debug=QuickHelper.getConfigValue(SystemConfigName.DEBUG,Boolean.class);
		if(!debug) {
			Integer smsValidSeconds=QuickHelper.getConfigIntegerValue(SystemConfigName.SMS_CONFIG_VALIDSECONDS);
			ValidateCodeEntity codeEntity = validateCodeService.getLastValidCodeEntry(mobile, smsValidSeconds);
			if (codeEntity == null) {
				return R.error("请您获取验证码");
			}

			if (!codeEntity.getCode().equals(form.getValidateCode())) {
				return R.error("验证码输入错误，请重新输入").put("ext", codeEntity);
			}

			//更新短信为已使用
			validateCodeService.updateState(codeEntity.getId(),1);
		}

		// 用户登录
		Map<String, Object> map = userService.login(form);

		return R.ok(map);
	}
	/**
	 * 退出登录
	 * @return
	 */

	@Login
	@PostMapping("logout")
	@ApiOperation("退出登录")
	public R logout() {
		String platform=HttpContextUtils.getHttpServletRequestHeaderPlatform();
		Long uid=(Long)HttpContextUtils.getHttpServletRequestHeaderValue("uid");
		tokenService.expireToken(uid,platform);
		return R.ok("已退出登录");
	}

	/**
	 * 检查登录状态
	 * 1、根据发送的 token 判断是否登录，大于 code > 0 为登录
	 * @return
	 *
	 * isNewUser =false 非新用户 true是新用户
	 */

	@RequestMapping("check")
	@ApiOperation("检查登录状态")
	public R check() {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		// 从header中获取token
		String token = request.getHeader("token");
		String platform = request.getHeader("platform");
		// 如果header中不存在token，则从参数中获取token
		if (StringUtils.isBlank(token)) {
			token = request.getParameter("token");
		}
		// token为空
		if (StringUtils.isBlank(token)) {
			throw new RRException("token不能为空", -101);
		}

		if(StringUtils.isBlank(platform)){
			throw new RRException("platform不能为空", -101);
		}
		// 查询token信息
		TokenEntity tokenEntity = tokenService.queryByToken(token,platform);
		if (tokenEntity == null || tokenEntity.getExpireTime().getTime() < System.currentTimeMillis()) {
			throw new RRException("token失效，请重新登录", -101);
		}
		//检查是否完善用户信息
		UserInfoEntity userInfoEntity=userInfoService.selectById(tokenEntity.getUserId());
		return R.ok("你已登录").put("data", tokenEntity).put("isNewUser", userInfoEntity == null);
	}
}
